home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / lisp / gdb.jl < prev    next >
Lisp/Scheme  |  1995-03-09  |  8KB  |  207 lines

  1. ;;;; gdb.jl -- run gdb in a buffer
  2. ;;;  Copyright (C) 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. ;;; This file is part of Jade.
  5.  
  6. ;;; Jade is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 2, or (at your option)
  9. ;;; any later version.
  10.  
  11. ;;; Jade is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;;; GNU General Public License for more details.
  15.  
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with Jade; see the file COPYING.  If not, write to
  18. ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. (require 'shell)
  21. (provide 'gdb)
  22.  
  23. (defvar gdb-file-name "gdb"
  24.   "The file name of the gdb program to run.")
  25.  
  26. (defvar gdb-auto-centre nil
  27.   "When non-nil the current line in the source window is automatically
  28. centred each time it changes.")
  29.  
  30. (defvar gdb-last-frame nil
  31.   "(FILE . LINE-NUMBER) representing the last frame we displayed.")
  32. (make-variable-buffer-local 'gdb-last-frame)
  33.  
  34. (defvar gdb-last-buffer nil
  35.   "This is the last *gdb* buffer which was used.")
  36.  
  37. (defvar gdb-buffer-p nil
  38.   "Flag that says this buffer is for running a gdb process.")
  39. (make-variable-buffer-local 'gdb-buffer-p)
  40.  
  41. (defvar gdb-spare-output nil)
  42. (make-variable-buffer-local 'gdb-spare-output)
  43.  
  44. (defvar gdb-delete-prompt nil)
  45. (make-variable-buffer-local 'gdb-delete-prompt)
  46.  
  47. (defvar gdb-ctrl-c-keymap (copy-sequence shell-ctrl-c-keymap))
  48. (bind-keys gdb-ctrl-c-keymap
  49.   "Ctrl-n" '(gdb-command "next %d\n" (prefix-numeric-argument current-prefix-arg))
  50.   "Ctrl-s" '(gdb-command "step %d\n" (prefix-numeric-argument current-prefix-arg))
  51.   "Ctrl-i" '(gdb-command "stepi %d\n" (prefix-numeric-argument current-prefix-arg))
  52.   "Ctrl-I" '(gdb-command "nexti %d\n" (prefix-numeric-argument current-prefix-arg))
  53.   "Ctrl-f" '(gdb-command "finish\n")
  54.   "Ctrl-r" '(gdb-command "cont\n")
  55.   "Ctrl-<" '(gdb-command "up %d\n" (prefix-numeric-argument current-prefix-arg))
  56.   "Ctrl->" '(gdb-command "down %d\n" (prefix-numeric-argument current-prefix-arg))
  57.   "Ctrl-b" '(gdb-command "break %s:%d\n" (gdb-current-file) (gdb-current-line))
  58.   "Ctrl-t" '(gdb-command "tbreak %s:%d\n" (gdb-current-file) (gdb-current-line))
  59.   "Ctrl-d" '(gdb-command "clear %d\n" (gdb-current-line))
  60.   "Ctrl-l" 'gdb-redisplay-frame)
  61.  
  62. (bind-keys ctrl-x-keymap
  63.   "Ctrl-a" '(setq next-keymap-path '(gdb-ctrl-c-keymap)))
  64.  
  65. ;;;###autoload
  66. (defun gdb (prog)
  67.   "Run the gdb debugger in an editor buffer (called `*gdb*'). PROG is the
  68. program which is to be debugged.
  69. See the `gdb-mode' documentation for details of the available commands.
  70. There is no limit to the number of gdb processes you may run at once."
  71.   (interactive "fProgram to debug:")
  72.   (let*
  73.       ((buffer (get-buffer "*gdb*")))
  74.     (if (or (not buffer) (with-buffer buffer shell-process))
  75.     (progn
  76.       (setq buffer (make-buffer "*gdb*"))
  77.       (set-buffer-special buffer t))
  78.       (clear-buffer buffer))
  79.     (goto-buffer buffer)
  80.     (kill-all-buffer-variables)
  81.     (set-buffer-file-name buffer prog)
  82.     (setq shell-program gdb-file-name
  83.       shell-program-args (list "-fullname" (file-name-nondirectory prog))
  84.       shell-prompt-regexp "^(.*\\(.+\\) *|.+---)"
  85.       shell-output-stream (list 'lambda '(x)
  86.                     (list 'gdb-output-filter
  87.                       (current-buffer)
  88.                       'x)))
  89.     (shell-mode)
  90.     (setq mode-name (concat "GDB:" (file-name-nondirectory prog))
  91.       major-mode 'gdb-mode
  92.       ctrl-c-keymap gdb-ctrl-c-keymap
  93.       gdb-last-buffer buffer
  94.       gdb-buffer-p t
  95.       mildly-special-buffer t)
  96.     (eval-hook 'gdb-hook)))
  97.  
  98. (defun gdb-mode ()
  99.   "Gdb Mode:\n
  100. This major-mode is used to run the GDB debugger in an editor buffer. To
  101. start a gdb subprocess use the `ESC x gdb' command.\n
  102. Each time the target process stops executing the source line of the
  103. current frame is highlighted in a separate window.\n
  104. The following commands are available in the `*gdb*' buffer,\n
  105.   `Ctrl-c Ctrl-n'    Next line
  106.   `Ctrl-c Ctrl-s'    Step 
  107.   `Ctrl-c Ctrl-i'    Step the next instruction
  108.   `Ctrl-c Ctrl-I'    Next instruction
  109.   `Ctrl-c Ctrl-f'    Finish this frame
  110.   `Ctrl-c Ctrl-r'    Continue execution
  111.   `Ctrl-c Ctrl-<'    Move up one frame
  112.   `Ctrl-c Ctrl->'    Move down one frame
  113.   `Ctrl-c Ctrl-b'    Set a breakpoint at the current line
  114.   `Ctrl-c Ctrl-t'    Set a temporary breakpoint
  115.   `Ctrl-c Ctrl-d'    Delete the breakpoint at the current line
  116.   `Ctrl-c Ctrl-l'    Redisplay the current frame\n
  117. They are also accessible in any buffer by replacing the `Ctrl-c' prefix
  118. with `Ctrl-x Ctrl-a'.\n
  119. Since this command is built on top of the shell-mode all commands from
  120. that mode are available as well.")
  121.  
  122.  
  123. ;; Digs the variable VAR out of the gdb-last-buffer
  124. (defmacro gdb-get-buffer-var (var)
  125.   (list 'with-buffer 'gdb-last-buffer var))
  126.  
  127. ;; Gets the name of the current file
  128. (defun gdb-current-file ()
  129.   (file-name-nondirectory (if gdb-buffer-p
  130.                   (car gdb-last-frame)
  131.                 (buffer-file-name))))
  132.  
  133. ;; Gets the current line number, it increments it as well
  134. (defun gdb-current-line ()
  135.   (1+ (if gdb-buffer-p
  136.       (cdr gdb-last-frame)
  137.     (pos-line (cursor-pos)))))
  138.  
  139. ;; Send a command to the correct gdb process
  140. (defun gdb-command (format-spec &rest format-args)
  141.   (when gdb-buffer-p
  142.     (setq gdb-last-buffer (current-buffer)))
  143.   (apply 'format
  144.      (gdb-get-buffer-var shell-process)
  145.      format-spec format-args)
  146.   (with-buffer gdb-last-buffer
  147.     (when (regexp-match-line "^\\(.*gdb.*\\) *" (buffer-end))
  148.       (setq gdb-delete-prompt t))))
  149.  
  150. ;; Receives all output from the gdb subprocess, it acts upon and removes
  151. ;; any frame markers
  152. (defun gdb-output-filter (buffer data)
  153.   (let
  154.       (new-frame)
  155.     (with-buffer buffer
  156.       (when gdb-spare-output
  157.     (setq data (concat gdb-spare-output data)))
  158.       (goto-buffer-end)
  159.       (when (and gdb-delete-prompt
  160.          (regexp-match-line shell-prompt-regexp))
  161.     (delete-area (match-start) (match-end))
  162.     (setq gdb-delete-prompt nil))
  163.       (while (regexp-match "\032\032([^:\n]+):([0-9]+):([0-9]+):.*\n" data)
  164.     ;; A whole marker to process
  165.     (insert (substring data 0 (match-start 0)))
  166.     (setq
  167.      gdb-last-frame (cons (substring data (match-start 1) (match-end 1))
  168.                   (1- (read (cons 0 (substring data
  169.                                (match-start 2)
  170.                                (match-end 2))))))
  171.      new-frame t
  172.      data (substring data (match-end 0))))
  173.       (if (regexp-match "\032" data)
  174.       ;; Start of an incomplete marker; save it for later
  175.       (progn
  176.         (insert (substring data 0 (match-start 0)))
  177.         (setq gdb-spare-output (substring data (match-start 0))))
  178.     (insert data)
  179.     (setq gdb-spare-output nil)))
  180.     (when new-frame
  181.       (setq gdb-last-buffer buffer)
  182.       ;; Now redisplay the frame and its highlight
  183.       (let*
  184.       ((frame (with-buffer buffer gdb-last-frame))
  185.        (window (if gdb-buffer-p (other-window) (current-window)))
  186.        (line-pos (pos 0 (cdr frame)))
  187.        old-buf)
  188.     (with-window window
  189.       (setq old-buf (current-buffer))
  190.       (goto-buffer (open-file (car frame)))
  191.       (mark-block line-pos (line-end line-pos))
  192.       (goto-char (line-end line-pos))
  193.       (when (or gdb-auto-centre (not (eq old-buf (current-buffer))))
  194.         (centre-display)))))))
  195.  
  196. (defun gdb-redisplay-frame ()
  197.   (interactive)
  198.   (when gdb-buffer-p
  199.     (setq gdb-last-buffer (current-buffer)))
  200.   (let*
  201.       ((frame (gdb-get-buffer-var gdb-last-frame))
  202.        (line-pos (pos 0 (cdr frame))))
  203.     (goto-buffer (open-file (car frame)))
  204.     (mark-block line-pos (line-end line-pos))
  205.     (goto-char (line-end line-pos))
  206.     (centre-display)))
  207.